
//
// 120122 - AH - Created.
//

package org.soekrat.engine.suite;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 *   Stores meta data for a class.
 * </p>
 * @author Arne Halvorsen (AH)
 */
public final class ClassMetaData  
{
  private final Class<?> m_class;
  
  private final Map<Locale, Set<String>> m_names=
    new HashMap<Locale, Set<String>>();
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param clazz Class storing meta data for.
   */
  public ClassMetaData(Class<?> clazz)
  { 
    if (clazz==null)
    {
      throw new NullPointerException("clazz");
    }
    
    m_class=clazz;
  }
  
  /**
   * <p>
   *   Gets class {@code this} has meta data for.
   * </p>
   * @return Class.
   */
  public Class<?> getClazz(){ return m_class; }
  
  /**
   * <p>
   *   Add names this is identified by in the default
   *   {@link Locale}.
   * </p>
   * @param names Names.
   */
  public void addNames(String... names){ addNames(Locale.getDefault(), names); }
  
  
  /**
   * <p>
   *   Add names this is identified by in the given 
   *   {@link Locale}.
   * </p>
   * @param locale {@code Locale} names are in.
   * @param names  Names.
   */
  public void addNames(Locale locale, String... names)
  {
    if (locale==null)
    {
      throw new NullPointerException("locale");
    }
    if (names==null)
    {
      throw new NullPointerException("name");
    }
    
    int n=names.length;
    for (int i=0; i<n; i++) 
    {
      String name=names[i];
      if (name==null)
      {
        throw new NullPointerException("names["+i+"]");
      }
      
      addName(locale, name);
    }
  }
  
  /**
   * <p>
   *   Adds name {@code this} is identified by in the default 
   *   {@link Locale}. 
   * </p>
   * @param name Name.
   */
  public void addName(String name){ addName(Locale.getDefault(), name); }
  
  /**
   * <p>
   *   Add name {@code this} is identified by in given
   *   {@link Locale}.
   * </p>
   * @param locale {@code Locale} {@code name} is in.
   * @param name   Name.
   */
  public void addName(Locale locale, String name)
  {
    if (locale==null)
    {
      throw new NullPointerException("locale");
    }
    if (name==null)
    {
      throw new NullPointerException("name");
    }
    
    Set<String> names=m_names.get(locale);
    if (names==null)
    {
      names=new HashSet<String>();
      m_names.put(locale, names);
    }
    names.add(name);
  }
  
  /**
   * <p>
   *   Tells if {@code this} is identified by given name in the default
   *   {@link Locale}.
   * </p>
   * @param name Name.
   * @return {@code true} if is, {@code false} if is not.
   */
  public boolean hasName(String name)
  { 
    return hasName(Locale.getDefault(), name); 
  }
  
  /**
   * <p>
   *   Tells if {@code this} is identified by given name in the given
   *   {@link Locale}.
   * </p>
   * @param locale {@link Locale} {@code name} is in.
   * @param name   Name to see if {@code this} is identified by.
   * @return {@code true} if is, {@code false} if is not.
   */
  public boolean hasName(Locale locale, String name)
  {
    if (locale==null)
    {
      throw new NullPointerException("locale");
    }
    if (name==null)
    {
      throw new NullPointerException("name");
    }
    
    Set<String> names=m_names.get(locale);
    return names==null ? false : names.contains(name);
  }
  
  /**
   * <p>
   *   Gets names {@code this} is identified by in the default
   *   {@link Locale}.
   * </p>
   * @return
   */
  public String[] getNames(){ return getNames(Locale.getDefault()); }
  
  private final static String[] E_STRING_A=new String[0];
  
  /**
   * <p>
   *   Gets names {@code this} is identified by in the given
   *   {@link Locale}.
   * </p>
   * @param locale {@code Locale}.
   * @return Names.
   */
  public String[] getNames(Locale locale)
  { 
    if (locale==null)
    {
      throw new NullPointerException("locale");
    }
    
    Set<String> names=m_names.get(locale);
    return names==null ? E_STRING_A : names.toArray(E_STRING_A);
  }
  
  private final static Locale[] E_LOCALE_A=new Locale[0];
  
  /**
   * <p>
   *   Get 
   *   {@link Locale}s names that identifies {@code this} are in.
   * </p>
   * @return {@code Locale}s.
   */
  public Locale[] getLocales()
  {
    return m_names.keySet().toArray(E_LOCALE_A);  
  }
  
  @Override
  public String toString()
  {
    StringBuilder sb=new StringBuilder();
    
    sb.append("class=").append(m_class.getName());
    if (m_names.size()>0)
    {
      boolean first=true;
      for (Map.Entry<Locale, Set<String>> curr : m_names.entrySet())
      {
        sb.append(", names=[");
        if (!first) sb.append(", ");
        first=false;
        sb.append("locale=").append(curr.getKey()).append(", names=")
          .append(curr.getValue());
      }
    }
    
    return sb.toString();
  }
  
}
